import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {Observable} from 'rxjs';
import {EurekaApplication} from 'src/app/entity/eureka-manage/eureka-application';
import * as _ from 'lodash';
import {tap} from 'rxjs/operators';
import {environment} from 'src/environments/environment';
import {EurekaInstance} from '../../entity/eureka-manage/eureka-instance';

const SERVICE_BASE = environment.backendServerBaseAddress;
const EUREKA_BASE = `${SERVICE_BASE}/eureka/manage`;

const STATUS_COLOR_MAP = {
  UP: 'green',
  DOWN: 'gray',
  STARTING: 'blue',
  OUT_OF_SERVICE: 'orange',
  UNKNOWN: 'purple',
};

@Injectable({
  providedIn: 'root'
})
export class EurekaManageService {

  constructor(private http: HttpClient) { }

  // ====↓ public api ↓====

  /**
   * 获取所有的Eureka Application
   * @param eurekaCode eureka code
   */
  public getAllEurekaApplications(eurekaCode: string): Observable<EurekaApplication[]> {
    return this.http.get<EurekaApplication[]>(`${EUREKA_BASE}/apps?eurekaCode=${eurekaCode}`)
      .pipe(tap(eurekaApplications => {
        for (const eurekaApplication of eurekaApplications) {
          eurekaApplication.instance = this.mapEurekaInstanceColor(eurekaApplication.instance);
        }
      }));
  }

  /**
   * Instance上线
   *
   * @param eurekaCode eureka code
   * @param applicationName 上线应用名称
   * @param instanceId 上线实例名称
   */
  public putStatusUp(eurekaCode: string, applicationName: string, instanceId: string): Observable<void> {
    if (_.isEmpty(applicationName) || _.isEmpty(instanceId)) {
      throw new Error('applicationName and instanceId should not be null');
    }
    return this.http.put<void>(`${EUREKA_BASE}/apps/put-status/up?eurekaCode=${eurekaCode}`, {app: applicationName, instanceId});
  }

  /**
   * Instance下线
   *
   * @param eurekaCode eureka code
   * @param applicationName 下线应用名称
   * @param instanceId 下线实例名称
   */
  public putStatusOutOfService(eurekaCode: string, applicationName: string, instanceId: string): Observable<void> {
    if (_.isEmpty(applicationName) || _.isEmpty(instanceId)) {
      throw new Error('applicationName and instanceId should not be null');
    }
    return this.http.put<void>(`${EUREKA_BASE}/apps/put-status/out-of-service?eurekaCode=${eurekaCode}`, 
      {app: applicationName, instanceId});
  }

  // ====↑ public api ↑====
  // ====↓ private api ↓====

  /**
   * 根据Eureka Instance状态渲染对应颜色
   *
   * @param eurekaInstances 待处理的Eureka Instance
   */
  private mapEurekaInstanceColor = (eurekaInstances: EurekaInstance[]) => {
    if (_.isEmpty(eurekaInstances)) {
      return [];
    }
    for (const instance of eurekaInstances) {
      instance.color = STATUS_COLOR_MAP[instance.status];
    }
    return eurekaInstances;
  }

  // ====↑ private api ↑====

}
